//||=========================================================================||
//||                                                                         ||
//||                       SimpleMandelbrotCounter.cpp                       ||
//||                                                                         ||
//||                           by the_best_goose))                           ||
//||                                                                         ||
//||=========================================================================||

#include <assert.h>
#include "SimpleMandelbrotCounter.h"
#include "MainWindow.h"

//-----------------------------------------------------------------------------

SimpleMandelbrotCounter::SimpleMandelbrotCounter(const MainWindow* pwind,
		                                         const QWidget* pmand_pic):
iters_count_(0),
px_size_(),
graph_rect_(),
pixels_(NULL),
y_trans_(0),
x_before_(0),
x_after_(0),
iters_(500),
index_array_(NULL),
break_(false)
{
    GenIndexes();

    connect(pwind, SIGNAL(IterationsCountChanged(int)),
            this, SLOT(SetIterationsCount(int)));
    connect(this, SIGNAL(Counted()), pmand_pic, SLOT(Repaint()));
    connect(this, SIGNAL(NeedRecount()), pmand_pic, SLOT(Recount()));
}

//-----------------------------------------------------------------------------

SimpleMandelbrotCounter::~SimpleMandelbrotCounter()
{
    break_ = true;
    wait();
    if (index_array_)
        delete[] index_array_;
}

//-----------------------------------------------------------------------------

void SimpleMandelbrotCounter::Init(QRgb* pixels, int y_trans, int x_before,
		                           int x_after, const QSize& px_rect,
		                           const QRectF& graph_rect)
{
    break_ = true;
    wait();
    break_ = false;
    assert(pixels != NULL);
    px_size_ = px_rect;
    graph_rect_ = graph_rect;
    pixels_ = pixels;
    y_trans_ = y_trans;
    x_before_ = x_before;
    x_after_ = x_after;
}

//-----------------------------------------------------------------------------

void SimpleMandelbrotCounter::run()
{
    double t = 1;
    assert(pixels_ != NULL);
    double re = 0, im = 0, c_re = 0, c_im = 0, temp_re = 0;
    int w = px_size_.width(), h = px_size_.height();
    for(int i = 0; i < w; ++i )
        for(int j = 0; j < h; ++j)
        {
            if (break_)
                return;
            re = c_re = i * graph_rect_.width() / w + graph_rect_.x();
            im = c_im = j * graph_rect_.height() / h +
            		    graph_rect_.y();
            for(iters_count_ = 0; iters_count_ < iters_; ++iters_count_)
            {
                temp_re = re;
                re = (re * re - im * im) * t + c_re +
                	 (re * re * re - 3 * re * im * im) * (1 - t);
                im = 2 * im * temp_re * t + c_im +
                     (3 * temp_re * temp_re * im - im * im * im) * (1 - t);
                if(re * re + im * im > 1000)
                    break;
            }
            pixels_[(j + y_trans_) * (w + x_before_ + x_after_) +
                    x_before_ + i] = GetColor();
        }
    emit Counted();
}

//-----------------------------------------------------------------------------

QRgb SimpleMandelbrotCounter::GetColor()
{
	assert(iters_count_ <= iters_);
    return index_array_[iters_count_];
}

//-----------------------------------------------------------------------------

void SimpleMandelbrotCounter::SetIterationsCount(int iters)
{
    assert(iters > 0);
	break_ = true;
    wait ( );
    break_ = false;
    iters_ = iters;
    GenIndexes();
    emit NeedRecount();
}

//-----------------------------------------------------------------------------

void SimpleMandelbrotCounter::GenIndexes()
{
    if(index_array_)
        delete[] index_array_;
    index_array_ = new QRgb[iters_ + 1];
    unsigned char r = 0, g = 0, b = 0;
    for(int i = iters_; i >= 0; --i)
    {
        b = 0;
        r = 0;
        g = 0;
        if(i != iters_)
        {
            g = i * 255 / iters_;
            b = (iters_ - i) * 255 * 0.07f / iters_;
            if(i < 50)
                r = i * 255 / 50;
        }
        index_array_[i] = qRgb(b, g, r);
    }
}

